package com.tianji.learning.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CategoryBasicDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.tianji.learning.service.IInteractionReplyService;
import com.tianji.learning.service.UserQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author xjs
 */
@Slf4j
@Service
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {

    @Autowired
    private UserClient userClient;
    @Autowired
    private SearchClient searchClient;
    @Autowired
    private CatalogueClient catalogueClient;
    @Autowired
    private CourseClient courseClient;
    @Autowired
    private CategoryClient categoryClient;
    @Autowired
    private CategoryCache categoryCache;
    @Autowired
    private UserQueryService userQueryService;

    @Autowired
    private IInteractionReplyService replyService;

    @Override
    public void addQuestion(QuestionFormDTO dto) {
        // 参数校验
//        Long courseId = dto.getCourseId();
//        if(courseId == null){
//            throw new BadRequestException("问题id不能为空");
//        }
//        String title = dto.getTitle();
//        if(StringUtils.isEmpty(title)){
//            throw new BadRequestException("问题标题不能为空");
//        }
//        if(title.length() < 1 || title.length() > 254){
//            throw new BadRequestException("问题标题长度要在1-254之间");
//        }
        // 。。。。。。。
        InteractionQuestion question = BeanUtil.copyProperties(dto, InteractionQuestion.class);
        question.setUserId(UserContext.getUser());
        question.setHidden(false);
        question.setStatus(QuestionStatus.UN_CHECK.getValue());
        question.setCreateTime(LocalDateTime.now());
        question.setUpdateTime(LocalDateTime.now());
        question.setAnswerTimes(0);
        this.save(question);
    }

    @Override
    public PageDTO<QuestionVO> pageQuery(QuestionPageQuery query) {
        Page<InteractionQuestion> page = query.toMpPage("create_time", false);
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(query.getCourseId()!=null, InteractionQuestion::getCourseId, query.getCourseId());
        queryWrapper.eq(query.getSectionId()!=null, InteractionQuestion::getSectionId, query.getSectionId());
        queryWrapper.eq(query.getOnlyMine()!=null&&query.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser());
        queryWrapper.eq(InteractionQuestion::getHidden, false);
        this.page(page, queryWrapper);
        List<InteractionQuestion> questions = page.getRecords();
        if(CollUtils.isEmpty(questions)){
            return PageDTO.empty(page);
        }
        // 批量查询reply
        List<InteractionReply> replies = null;
        Map<Long, InteractionReply> replyMap = null;
        List<Long> replyUserIds = null;
        List<Long> relyIds = questions.stream().filter(q -> q.getLatestAnswerId() != null)
                .map(InteractionQuestion::getLatestAnswerId).collect(Collectors.toList());
        if(!CollUtils.isEmpty(relyIds)){
            replies = replyService.listByIds(relyIds);
            if(CollUtils.isEmpty(replies)){
                log.info("查询不到reply信息：{}", relyIds);
                throw new BizIllegalException("网络异常");
            }
            replyMap = replies.stream().collect(Collectors.toMap(InteractionReply::getId, r -> r));
        }
        if(CollUtils.isNotEmpty(replies)){
            replyUserIds = replies.stream()
                    .filter(r->r.getAnonymity()!=null && !r.getAnonymity())
                    .map(InteractionReply::getUserId).distinct().collect(Collectors.toList());
        }

        // userClient批量查询用户
        Map<Long, UserDTO> userMap = new HashMap<>();
        List<Long> questionUserIds = questions.stream()
                // 过滤出来不需要匿名的用户
                .filter(q->q.getAnonymity()!=null && !q.getAnonymity())
                // 获取用户的id
                .map(InteractionQuestion::getUserId).distinct().collect(Collectors.toList());
        // 合并question和reply中的useId，批量feign调用
        Set<Long> userSet = new HashSet<>();
        if(CollUtils.isNotEmpty(questionUserIds)){
            userSet.addAll(questionUserIds);
        }
        if(CollUtils.isNotEmpty(replyUserIds)){
            userSet.addAll(replyUserIds);
        }
        List<Long> userIds = new ArrayList<>(userSet);
        if(CollUtils.isNotEmpty(userIds)){
            List<UserDTO> userList = userClient.queryUserByIds(userIds);
            if(CollUtils.isEmpty(userIds)){
                log.info("查询不到用户信息：{}", questionUserIds);
                throw new BizIllegalException("网络异常");
            }
            userMap = userList.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }
        // InteractionQuestion =》 QuestionVO
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion question : questions) {
            QuestionVO vo = BeanUtil.copyProperties(question, QuestionVO.class);
            // username usericon
            if(question.getAnonymity()==null || !question.getAnonymity()){
                UserDTO user = userMap.get(question.getUserId());
                vo.setUserName(user==null?"":user.getName());
                vo.setUserIcon(user==null?"":user.getIcon());
            }
            // latest_reply_content latest_reply_user
            if(CollUtils.isNotEmpty(replyMap) && question.getLatestAnswerId()!=null){
                InteractionReply reply = replyMap.get(question.getLatestAnswerId());
                vo.setLatestReplyContent(reply==null?"":reply.getContent());
                if(reply != null && reply.getAnonymity()!=null && !reply.getAnonymity()){
                    Long replyUserId = reply.getUserId();
                    UserDTO replyUser = userMap.get(replyUserId);
                    vo.setLatestReplyUser(replyUser==null?"":replyUser.getName());
                }else{
                    vo.setLatestReplyUser("匿名用户");
                }
            }
            voList.add(vo);
        }
        return PageDTO.of(page, voList);
    }

    @Override
    public QuestionVO details(Long id) {
        InteractionQuestion question = this.getById(id);
        if(question == null){
            return null;
        }
        QuestionVO vo = BeanUtil.copyProperties(question, QuestionVO.class);
        // 填充用户信息
        if(!question.getAnonymity()){
            Long userId = question.getUserId();
            UserDTO user = userClient.queryUserById(userId);
            if(user == null){
                log.info("查询不到用户信息：{}", userId);
                throw new BizIllegalException("网络异常");
            }
            vo.setUserName(user.getName());
            vo.setUserIcon(user.getIcon());
        }
        return vo;
    }

    @Override
    public PageDTO<QuestionAdminVO> adminPageQuery(QuestionAdminPageQuery query) {
        // 分页条件
        Page<InteractionQuestion> page = query.toMpPage("create_time", false);
        // 查询条件
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = getLambdaQueryWrapper(query);
        if(queryWrapper == null){
            return PageDTO.empty(page);
        }
        // 分页查询
        this.page(page, queryWrapper);
        List<InteractionQuestion> questions = page.getRecords();
        if(CollUtils.isEmpty(questions)){
            return PageDTO.empty(page);
        }
        // 查询章节信息
        Map<Long, CataSimpleInfoDTO> catalogueMap = getCatalogueMap(questions);
        // 查询课程信息
        Map<Long, CourseSimpleInfoDTO> courseMap = getCourseMap(questions);
        // 查询用户信息
        Map<Long, UserDTO> userMap = userQueryService.queryUserMap(questions);
        // 查询分类信息
        Map<Long, CategoryBasicDTO> categoryMap = getCategoryMap();
        // InteractionQuestion =》 QuestionAdminVO
        List<QuestionAdminVO> voList = new ArrayList<>(questions.size());
        for (InteractionQuestion question : questions) {
            QuestionAdminVO vo = BeanUtil.copyProperties(question, QuestionAdminVO.class);
            // chapterName、sectionName =》catalogueClient
            CataSimpleInfoDTO chapter = catalogueMap.get(question.getChapterId());
            CataSimpleInfoDTO section = catalogueMap.get(question.getSectionId());
            vo.setChapterName(chapter==null?"":chapter.getName());
            vo.setSectionName(section==null?"":section.getName());
            //courseName =》 courseClient
            CourseSimpleInfoDTO course = courseMap.get(question.getCourseId());
            vo.setCourseName(course==null?"":course.getName());
            // userName =》 userClient
            UserDTO user = userMap.get(question.getUserId());
            vo.setUserName(user==null?"":user.getName());
            // categoryName =》 categoryClient
            AssertUtils.isNotNull(course, "课程信息不存在");
            vo.setCategoryName(categoryCache.getNameByLv3Id(course.getThirdCateId()));
            voList.add(vo);
        }
        return PageDTO.of(page, voList);
    }

    private LambdaQueryWrapper<InteractionQuestion>  getLambdaQueryWrapper(QuestionAdminPageQuery query){
        LambdaQueryWrapper<InteractionQuestion> queryWrapper = new LambdaQueryWrapper<>();
        // courseName  =》 courseIds
        if(StringUtils.isNotBlank(query.getCourseName())){
            List<Long> courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if(CollUtils.isEmpty(courseIds)){
                return null;
            }
            queryWrapper.in(InteractionQuestion::getCourseId, courseIds);
        }
        queryWrapper.eq(query.getStatus() != null, InteractionQuestion::getStatus, query.getStatus());
        queryWrapper.ge(query.getBeginTime()!=null, InteractionQuestion::getCreateTime, query.getBeginTime() );
        queryWrapper.le(query.getEndTime()!=null, InteractionQuestion::getCreateTime, query.getEndTime() );
        return queryWrapper;
    }

    private String getCategoryNames(Map<Long, CategoryBasicDTO> categoryMap, CourseSimpleInfoDTO course){
        AssertUtils.isNotNull(course, "课程信息不存在");
        CategoryBasicDTO category1 = categoryMap.get(course.getFirstCateId());
        CategoryBasicDTO category2 = categoryMap.get(course.getSecondCateId());
        CategoryBasicDTO category3 = categoryMap.get(course.getThirdCateId());
        return (category1==null?"":category1.getName())+"/"+(category2==null?"":category2.getName())+"/" + (category3==null?"":category3.getName());
    }

    private Map<Long, CategoryBasicDTO>  getCategoryMap(){
        List<CategoryBasicDTO> categoryList = categoryClient.getAllOfOneLevel();
        if(CollUtils.isEmpty(categoryList)){
            log.info("查询不到分类信");
            throw new BizIllegalException("网络异常");
        }
        Map<Long, CategoryBasicDTO> categoryMap = categoryList.stream().collect(Collectors.toMap(CategoryBasicDTO::getId, Function.identity()));
        return CollUtils.isEmpty(categoryMap)?new HashMap<>():categoryMap;
    }

//    private Map<Long, UserDTO> getUserMap(List<InteractionQuestion> questions){
//        List<Long> userIds = questions.stream().map(InteractionQuestion::getUserId).distinct().collect(Collectors.toList());
//        List<UserDTO> users = userClient.queryUserByIds(userIds);
//        if(CollUtils.isEmpty(users)){
//            log.info("查询不到用户信息：{}", userIds);
//            throw new BizIllegalException("网络异常");
//        }
//        Map<Long, UserDTO> userMap = users.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
//        return CollUtils.isEmpty(userMap)?new HashMap<>():userMap;
//    }

    private Map<Long, CourseSimpleInfoDTO> getCourseMap(List<InteractionQuestion> questions){
        List<Long> courseIds = questions.stream().map(InteractionQuestion::getCourseId).distinct().collect(Collectors.toList());
        List<CourseSimpleInfoDTO> courseList = courseClient.getSimpleInfoList(courseIds);
        if(CollUtils.isEmpty(courseList)){
            log.info("查询不到课程信息：{}", courseIds);
            throw new BizIllegalException("网络异常");
        }
        Map<Long, CourseSimpleInfoDTO> courseMap = courseList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        return CollUtils.isEmpty(courseMap)?new HashMap<>():courseMap;
    }

    private Map<Long, CataSimpleInfoDTO> getCatalogueMap(List<InteractionQuestion> questions){
        Map<Long, CataSimpleInfoDTO> catalogueMap = new HashMap<>();
        Set<Long> sectionIds = new HashSet<>();
        questions.stream().forEach(q->{
            if(q.getChapterId() != null){
                sectionIds.add(q.getChapterId());
            }
            if(q.getSectionId() != null){
                sectionIds.add(q.getSectionId());
            }
        });
        if(CollUtils.isNotEmpty(sectionIds)){
            List<CataSimpleInfoDTO> catalogues = catalogueClient.batchQueryCatalogue(sectionIds);
            if(CollUtils.isEmpty(catalogues)){
                log.info("查询不到章节信息：{}", sectionIds);
                throw new BizIllegalException("网络异常");
            }
            catalogueMap = catalogues.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, Function.identity()));
        }
        return catalogueMap;
    }

}
